#include "re_config.h"
#include "pcre_internal.h"

/*************************************************
 *       Match character against an XCLASS        *
 *************************************************/

/* This function is called to match a character against an extended class that
might contain values > 255.

Arguments:
  c           the character
  data        points to the flag byte of the XCLASS data

Returns:      TRUE if character matches, else FALSE
*/

BOOL _pcre_xclass(int c, const uschar* data) {
    int t;
    BOOL negated = (*data & XCL_NOT) != 0;

    /* Character values < 256 are matched against a bitmap, if one is present.
    If not, we still carry on, because there may be ranges that start below 256
    in the additional data. */

    if (c < 256) {
        if ((*data & XCL_MAP) != 0 && (data[1 + c / 8] & (1 << (c & 7))) != 0)
            return !negated; /* char found */
    }

    /* First skip the bit map if present. Then match against the list of Unicode
    properties or large chars or ranges that end with a large char. We won't
    ever encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */

    if ((*data++ & XCL_MAP) != 0)
        data += 32;

    while ((t = *data++) != XCL_END) {
        int x, y;
        if (t == XCL_SINGLE) {
            GETCHARINC(x, data);
            if (c == x)
                return !negated;
        } else if (t == XCL_RANGE) {
            GETCHARINC(x, data);
            GETCHARINC(y, data);
            if (c >= x && c <= y)
                return !negated;
        }
#ifdef SUPPORT_UCP
        else /* XCL_PROP & XCL_NOTPROP */
        {
            int chartype, script;
            int category = _pcre_ucp_findprop(c, &chartype, &script);

            switch (*data) {
                case PT_ANY:
                    if (t == XCL_PROP)
                        return !negated;
                    break;

                case PT_LAMP:
                    if ((chartype == ucp_Lu || chartype == ucp_Ll ||
                         chartype == ucp_Lt) == (t == XCL_PROP))
                        return !negated;
                    break;

                case PT_GC:
                    if ((data[1] == category) == (t == XCL_PROP))
                        return !negated;
                    break;

                case PT_PC:
                    if ((data[1] == chartype) == (t == XCL_PROP))
                        return !negated;
                    break;

                case PT_SC:
                    if ((data[1] == script) == (t == XCL_PROP))
                        return !negated;
                    break;

                    /* This should never occur, but compilers may mutter if
                    there is no default. */

                default:
                    return FALSE;
            }

            data += 2;
        }
#endif /* SUPPORT_UCP */
    }

    return negated; /* char did not match */
}

/* End of pcre_xclass.c */
